package TimeCounter;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Arrays;

import java.util.HashMap;

public class CglibProxy<T> implements MethodInterceptor {

    private int runTimes = 1;
    HashMap<String, Integer> map = new HashMap<>();
    HashMap<String, Integer> spaceMap = new HashMap<>();

    //代理方法
    public T createProxy(T target){
        Enhancer enhancer = new Enhancer();// 创建一个动态类对象
        enhancer.setSuperclass(target.getClass());// 确定需要增强的类，设置其父类
        enhancer.setCallback(this);// 添加回调函数
        return (T) enhancer.create(); // 返回创建的代理类
    }

    /**
     * SimpleDateFormat丞数语法:
     * G 年代标志符
     * y 年
     * M 月
     * d 日
     * h 时 上午或下午(1~12)
     * H 时在一天中(0~23)
     * m 分
     * s 秒
     * S 毫秒
     * E 星期
     * D 一年中的第几天
     * F 一月中第几个星期几
     * w 一年中第几个星期
     * W 一月中第几个星期
     * a 上午/下午标记符
     * k 时在一天中（(1~24)
     * K 时在上午或下午(0~11)
     * z 时区
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        map.putIfAbsent(method.getName(), 0);
        if (runTimes == 1){
            methodProxy.invokeSuper(proxy, args); // 第一次运行时间比较长，直接运行
            System.out.println("屏蔽第一次运行导致的长时间,向下翻");
            for (int i = 0; i < 50; i++) {
                System.out.println();
            }
        }
            // 由于有的时候函数递归，所以计算次数的标志不能放在最后。
        runTimes++;
        map.replace(method.getName(),map.get(method.getName()) + 1);// 统计一个函数执行的次数

        System.out.println(">>第 " + map.get(method.getName()) + " 次运行" + method.getName() + "<<");
        System.out.println("打印情况：");

        long time1 = System.nanoTime(); // 函数执行前
        Object obj = methodProxy.invokeSuper(proxy, args); // 执行函数
        long time2 = System.nanoTime();

        long time = time2 - time1;// 计算时间差值 单位纳秒
        String unit = "纳秒"; //单位
        if (time >= 1_000_000){
            time /= 1_000_000;
            unit = "毫秒";
        }
        System.out.println("耗时 " + time + " "+ unit);
        System.out.println("参数列表: " + Arrays.deepToString(args));

        if (obj != null && obj.getClass().isArray()){ // 将object对象转换为数组
            int len = Array.getLength(obj);
            Object[] objArray = new Object[len];
            for(int i = 0; i < len; i++) {
                objArray[i] = Array.get(obj, i);
            }
            System.out.println("运行结果: " + Arrays.deepToString(objArray));
        }else {
            System.out.println("运行结果: " + obj);
        }

        return obj;
    }

    private void print(String methodNameAndTime){
        String space = " "; //缩进单位
        //TODO
//        spaceMap.putIfAbsent(methodNameAndTime,)
    }


//    @Test
//    public void test(){ // 测试方法 jdk8 以上版本运行时要添加此参数 java --add-opens java.base/java.lang=ALL-UNNAMED
//        Code01 code01 = new as.CglibProxy<Code01>().createProxy(new Code01());
//        System.out.println(Arrays.toString(code01.handler1(new int[]{2, 7, 11, 15}, 9)));
//    }
}
